#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "filedispat.h"
#include "like.h"
#include "epoll.h"
#include "data_packet.h"

int fd_ergodic_list(const char *name ,userinfo *head);

int get_filesize(const char *pathname,int *fd)
{
	struct stat st;
	if(access(pathname,F_OK))
		return 0;
	*fd = open(pathname,O_RDONLY);
	stat(pathname,&st);
	return st.st_size;
}

int server_transfer_data(Conndata *data,char *buf)
{
	int mark,target_fd;
	char name[64];
	char target[64];
	readn(data->event_fd,buf,SOCK_BUF_SIZE);
	sscanf(buf,"%d %s %s",&mark,name,target);
	target_fd = fd_ergodic_list(target,head);
	if(target_fd == -1){
			send_file_error(data->event_fd);
			return -1;
	}
	writen(target_fd, buf, SOCK_BUF_SIZE);
	return 0;
}

int send_file(int net_fd,int file_fd,size_t n,filestruct *data,const char *user)
{
	int mark = 6;
	size_t file_size = n;
	size_t count = 0;
	ssize_t readval = 0;
	char buf[SOCK_BUF_SIZE]={0};
	//printf("file_size = %d\n",file_size);
	while(1){
		sleep(1);
		bzero(buf,SOCK_BUF_SIZE);
		lseek(file_fd,count,SEEK_SET);		
		sprintf(buf,"%d%s %s ",mark,user,data->target_user);
		//printf("%s:\n",buf);
		readval = readn(file_fd,buf+strlen(buf),(size_t)(SOCK_BUF_SIZE - strlen(buf)));
		//printf("%d %d\n",sizeof(buf),strlen(buf));
		//printf("%d %d:",count,readval);
		printf("#");
		fflush(stdout);
		count += readval;
		if(count == file_size){
			writen(net_fd,buf,SOCK_BUF_SIZE);
			//printf("%s",buf);
			break;
		}else{
			writen(net_fd,buf,SOCK_BUF_SIZE);
			//printf("%s",buf);
			continue;
		}
	}
	printf("\nFile sending completed!!!\n");
	return 0;
}


int send_file_data(int fd,char *data,struct filestruct *file_data,const char *name)
{
	int ret;
	sprintf(data,"%d %d %d %d %s %s %s",file_data->mark,file_data->fd_size,\
							  file_data->file_size,file_data->name_size,\
							  file_data->filename,file_data->target_user,name);
	
	printf("*****%s*****\n",data);
	ret = writen(fd,data,SOCK_BUF_SIZE);
	if(ret==-1)
		perror("writen:");
	
	return 0;
}

int recv_file_data(int fd,char *data,struct filestruct *file_data,char *name)
{
	//int iread;
	memset(file_data,0,sizeof(filestruct));
	//iread = readn(fd,data,SOCK_BUF_SIZE);
	sscanf(data,"%d %d %d %d ",&file_data->mark,&file_data->fd_size,\
							  &file_data->file_size,&file_data->name_size);
	file_data->filename = (char *)malloc(file_data->file_size);
	file_data->target_user = (char *)malloc(file_data->name_size);
	sscanf(data,"%d %d %d %d %s %s %s",&file_data->mark,&file_data->fd_size,\
							  &file_data->file_size,&file_data->name_size,\
							  file_data->filename,file_data->target_user,name);
	printf("\n\n%d %d %d %d %s %s %s\n\n",file_data->mark,file_data->fd_size,\
							  file_data->file_size,file_data->name_size,\
							  file_data->filename,file_data->target_user,name);
	//printf("******%s*****\n",data);
	return 0;
}

ssize_t recvn_read_only(int fd, void *vptr, size_t n)
{
	size_t nleft;
	ssize_t nread;
	char *ptr;

	ptr = vptr;
	nleft = n;

	while (nleft > 0) {
		if ( (nread = recv(fd, ptr, nleft,MSG_PEEK)) < 0) {
			if (errno == EINTR)
				nread = 0;
			else
				return -1;
		} else if (nread == 0)
			break;
		else if (nread != nleft){
			nleft -= nread;
			ptr += nread;
			break;
		}
		nleft -= nread;
		ptr += nread;
	}
	return n - nleft;
}
//else if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)

ssize_t readn(int fd, void *vptr, size_t n)
{
	size_t nleft;
	ssize_t nread;
	char *ptr;

	ptr = vptr;
	nleft = n;

	while (nleft > 0) {
		if ( (nread = read(fd, ptr, nleft)) < 0) {
			if (errno == EINTR)
				nread = 0;
			else
				return -1;
		} else if (nread == 0)
			break;
		nleft -= nread;
		ptr += nread;
	}
	return n - nleft;
}


ssize_t writen(int fd, const void *vptr, size_t n)
{
	size_t nleft;
	ssize_t nwritten;
	const char *ptr;

	ptr = vptr;
	nleft = n;

	while (nleft > 0) {
		if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
			if (nwritten < 0 && errno == EINTR)
				nwritten = 0;
			else
				return -1;
		}
		nleft -= nwritten;
		ptr += nwritten;
	}
	return n;
}

int read_fifo_mark(int fd)
{
	int mark,ret;
	char pbuf[1]={0};
	while(1){
		ret = recv(fd,pbuf,1,MSG_PEEK);
		if(ret == -1)
			return -2;
		else if(ret == 0)
			return -1;
		else if(ret == 1){
			break;
		}
	}
	sscanf(pbuf,"%d",&mark);
	printf("%d*******\n",mark);
	return mark;
}

